<template>
    <div class="property-edit">
        <el-tabs v-model="currentTab">
            <el-tab-pane :label="item.label" :name="item.name" v-for="(item, index) in tabs" :key="index"></el-tab-pane>
        </el-tabs>
        <el-scrollbar class="property-edit-tab-content">
            <div class="property-edit-form">
                <!-- 字段属性 -->
                <VoSchemaForm v-if="model && currentTab === 'prop'" :model="model" :schema="propsSchema" :rules="rules">
                    <!-- 字段标识 -->
                    <template #model="{ model }">
                        <div class="model-edit">
                            <el-input v-if="isModelEdit" v-model.trim="modelValue" size="small" placeholder="请输入唯一字段值">
                                <el-button slot="append" icon="el-icon-check" @click="modelEditSave"></el-button>
                            </el-input>
                            <div v-else class="model-edit-text">
                                <span>{{model.model}}</span>
                            </div>
                            <el-divider direction="vertical"></el-divider>
                            <el-button size="small" type="text" @click="modelEditToggle">
                                {{isModelEdit ? '取消' : '修改'}}
                            </el-button>
                        </div>
                    </template>

                    <!-- 公用 -->
                    <template #_common>
                        <div class="property-edit-form-common">
                            <span>公用</span>
                            <el-button type="text" icon="el-icon-set-up" @click="formItemShowHidden('common')"></el-button>
                        </div>
                    </template>

                    <!-- 私有 -->
                    <template #_private>
                        <div class="property-edit-form-common">
                            <span>私有</span>
                            <el-button type="text" icon="el-icon-set-up" @click="formItemShowHidden('private')"></el-button>
                        </div>
                    </template>
                    <!-- 数据源 -->
                    <template #enum="{ model }">
                        <div>
                            <el-button @click="openEnumEdit">静态数据源</el-button>
                            <div>
                                <el-checkbox v-model="model.source.use" @change="sourceBindChange">绑定数据源</el-checkbox>
                                <div v-if="model.source.use">
                                    <el-select v-model="sourceValue" clearable @change="handleSource" style="width: 100%;" placeholder="可选择绑定动态数据源">
                                        <el-option
                                            v-for="(item, index) in formSource"
                                            :key="index"
                                            :label="item.name"
                                            :value="item.id">
                                        </el-option>
                                    </el-select>
                                    <p>数据路径</p>
                                    <el-input v-model="model.source.resPath" placeholder="请输入数据路径"></el-input>
                                    <p>绑定值的key</p>
                                    <el-input v-model="model.source.labelKey" placeholder="请输入绑定值的key"></el-input>
                                    <p>展示值的key</p>
                                    <el-input v-model="model.source.valueKey" placeholder="请输入展示值的key"></el-input>
                                    <p>子选项的key</p>
                                    <el-input v-model="model.source.childrenKey" placeholder="请输入子选项的key"></el-input>
                                </div>
                            </div>
                        </div>
                    </template>

                    <!-- 校验规则 -->
                    <template #_rules>
                        <div class="property-edit-form-common">
                            <span>校验规则</span>
                            <el-button type="text" icon="el-icon-set-up" @click="formItemShowHidden('rules')"></el-button>
                        </div>
                    </template>
                    <!-- 校验 -->
                    <template #rules>
                        <ul class="rules" v-if="model.rules && model.rules.length">
                            <li class="rules-item" v-for="(item, index) in model.rules" :key="index">
                                <el-checkbox v-model="item._checked">{{item._name}}</el-checkbox>
                                <div class="rules-message" v-if="item._checked">
                                    <el-row v-if="item._type === 'type'">
                                        <el-col :span="6">值类型</el-col>
                                        <el-col :span="18">
                                            <el-select
                                                v-model="item.type"
                                                :disabled="!item._checked"
                                                clearable
                                                placeholder="请选择检验类型"
                                            >
                                                <el-option v-for="(t, i) in typeGroup" :key="i" :label="t.label" :value="t.value"></el-option>
                                            </el-select>
                                        </el-col>
                                    </el-row>
                                    <el-row v-if="item._type === 'pattern'">
                                        <el-col :span="6">表达式</el-col>
                                        <el-col :span="18">
                                            <el-input v-model="item.pattern" placeholder="能通过RegExp无异常的字符串"></el-input>
                                        </el-col>
                                    </el-row>
                                    <el-row>
                                        <el-col :span="6">校验提示</el-col>
                                        <el-col :span="18"><el-input v-model="item.message" placeholder="校验提示"></el-input></el-col>
                                    </el-row>
                                    <el-row>
                                        <el-col :span="6">触发方式</el-col>
                                        <el-col :span="18">
                                            <el-select
                                                v-model="item.trigger"
                                                :disabled="!item._checked"
                                                clearable
                                                multiple
                                                placeholder="请选择触发方式"
                                            >
                                                <el-option label="change" value="change"></el-option>
                                                <el-option label="blur" value="blur"></el-option>
                                                <el-option label="input" value="input"></el-option>
                                            </el-select>
                                        </el-col>
                                    </el-row>
                                </div>
                            </li>
                        </ul>
                    </template>
                    <!-- 操作 -->
                    <template #footer>
                        <span></span>
                    </template>
                </VoSchemaForm>

                <!-- 表单属性 -->
                <VoSchemaForm v-if="formModel && currentTab === 'form'" :model="formModel" :schema="formSchema" :rules="rules">
                    <!-- 表单属性 -->
                    <template #_form>
                        <div class="property-edit-form-common">
                            <span>表单属性</span>
                            <el-button type="text" icon="el-icon-set-up" @click="formShowHidden('form')"></el-button>
                        </div>
                    </template>
                    <!-- 表单属性 -->
                    <template #_enum>
                        <div class="property-edit-form-common">
                            <span>数据源</span>
                            <el-button type="text" icon="el-icon-set-up" @click="formShowHidden('enum')"></el-button>
                        </div>
                    </template>
                    <!-- 数据源 -->
                    <template #enum>
                        <div style="margin-top: 20px;">
                            <el-button @click="openSourceConfig">数据源设置</el-button>
                        </div>
                    </template>

                    <!-- 操作 -->
                    <template #footer>
                        <span></span>
                    </template>
                </VoSchemaForm>
            </div>
        </el-scrollbar>

        <!-- 数据源: 静态 -->
        <el-dialog
            title="数据源"
            width="1000px"
            :visible.sync="enumVisible">
            <VoDragFormPropertyEditEnum ref="enumEdit" :property="property"></VoDragFormPropertyEditEnum>
            <span slot="footer" class="dialog-footer">
                <el-button @click="enumVisible = false">取 消</el-button>
                <el-button type="primary" @click="enumConfirm">确 定</el-button>
            </span>
        </el-dialog>

        <!-- 数据源: 动态 -->
        <el-dialog
            title="数据源"
            width="1000px"
            :visible.sync="sourceVisible">
            <VoDragFormDataSource ref="source"></VoDragFormDataSource>
        </el-dialog>
    </div>
</template>

<script>
import { mapState } from 'vuex'
import { rulesTypeGroup } from '../utils/drag'
import { clone } from '@/utils/clone'
import VoDragFormPropertyEditEnum from './PropertyEditEnum.vue'
import PropertyEditSchema from '@/components/utils/property-edit-schema'
import { schemaEditSchema } from '@/components/utils/schema-edit-schema'
import VoDragFormDataSource from './components/DataSource.vue'

export default {
    name: 'VoDragFormPropertyEdit',
    components: {
        VoDragFormPropertyEditEnum,
        VoDragFormDataSource
    },
    props: {
        widgets: Array,
        property: Object,
        schema: Object
    },
    computed: {
        ...mapState({
            formSource: state => state.schemaSource.formSource || []
        }),
        model: {
            get() {
                return this.property
            }
        },
        formModel: {
            get() {
                return this.schema
            }
        }
    },
    watch: {
        property(value) {
            this.$nextTick(() => {
                if (value) {
                    this.resetPropsSchema()
                }
                this.isModelEdit = false
            })
        }
    },
    data() {
        return {
            currentTab: 'prop',
            tabs: [
                { label: '字段属性', name: 'prop' },
                { label: '表单属性', name: 'form' }
            ],
            // 字段属性schema
            propsSchema: {
                properties: {},
                ui: {
                    labelPosition: 'top',
                    size: 'small'
                }
            },
            modelValue: null,
            isModelEdit: false,
            // 规则 type 可选项
            typeGroup: rulesTypeGroup,
            // 表单属性schema
            formSchema: schemaEditSchema,
            // 规则
            rules: {
                model: [
                    { required: true, message: '必填项', trigger: ['change', 'blur'] },
                    { pattern: /^[A-Za-z]\w*$/, message: '只能包含字母、数字、下划线组成，且以字母开头', trigger: ['change', 'blur'] },
                    { validator: this.modelValid, trigger: ['change', 'blur'] }
                ]
            },
            // 数据源
            enumVisible: false,
            sourceVisible: false,
            sourceValue: null
        }
    },
    methods: {
        /**
         * 设置表单编辑 schema
        */
        resetPropsSchema() {
            const { widget } = this.property
            this.propsSchema.properties = [
                {
                    model: '_common',
                    widget: 'custom',
                    label: ''
                },
                ...(PropertyEditSchema.common || []).map(e => ({ ...e, _mode: 'common', hidden: false })),
                {
                    model: '_private',
                    widget: 'custom',
                    label: ''
                },
                ...(PropertyEditSchema[widget] || []).map(e => ({ ...e, _mode: 'private', hidden: false })),
                {
                    model: '_rules',
                    widget: 'custom',
                    label: ''
                },
                ...(PropertyEditSchema.rules || []).map(e => ({ ...e, _mode: 'rules', hidden: false }))
            ].reduce((t, e) => {
                t[e.model] = e
                return t
            }, {})
        },
        /**
         * model 字段重复校验
        */
        modelValid(rule, value, cb) {
            if (this.widgets.indexOf(value) !== this.widgets.lastIndexOf(value)) {
                cb(new Error('字段重复'))
            } else {
                cb()
            }
        },
        /**
         * 动态数据源
        */
        sourceBindChange(e) {
            if (e && this.model.source.http) {
                this.sourceValue = this.model.source.http.id
            }
        },
        handleSource(e) {
            const item = this.formSource.find(v => v.id === e)
            if (item) {
                this.model.source.http = clone(item)
            } else {
                this.sourceValue = null
                this.$message.error('绑定失败')
            }
        },
        /**
         * 静态数据源编辑
        */
        openEnumEdit() {
            this.enumVisible = true;
            this.$nextTick(() => {
                this.$refs.enumEdit.setValue(this.property.enum)
            })
        },
        /**
         * 静态数据源编辑确定
        */
        enumConfirm() {
            if (['colorPicker', 'ColorPicker'].indexOf(this.property.widget) !== -1) {
                this.enumVisible = false;
            } else {
                if (this.$refs.enumEdit && this.$refs.enumEdit.editor) {
                    const { editor } = this.$refs.enumEdit;
                    const value = editor.getValue();
                    if (value) {
                        let data = [];
                        try {
                            data = JSON.parse(value)
                        } catch (error) {
                            this.$message.error(error.message)
                            return;
                        }
                        if (Array.isArray(data)) {
                            this.enumVisible = false;
                            this.setEnum(data)
                        } else {
                            this.$message.warning('输入数据不符合要求')
                        }
                    } else {
                        this.enumVisible = false;
                        this.deleteEnum()
                    }
                }
            }
        },
        /**
         * 移除 enum 字段
        */
        deleteEnum() {
            this.$delete(this.model, 'enum')
        },
        /**
         * 设置 enum 字段
        */
        setEnum(arr) {
            this.$set(this.model, 'enum', arr)
        },
        /**
         * 显示/隐藏
        */
        formItemShowHidden(mode) {
            const { properties } = this.propsSchema
            for (const key in properties) {
                const element = properties[key]
                if (element._mode === mode) {
                    this.$set(element, 'hidden', !element.hidden)
                }
            }
        },
        /**
         * 动态数据源
        */
        openSourceConfig() {
            this.sourceVisible = true
        },
        /**
         * 显示/隐藏
        */
        formShowHidden(mode) {
            const { properties } = this.formSchema
            for (const key in properties) {
                const element = properties[key]
                if (element._mode === mode) {
                    this.$set(element, 'hidden', !element.hidden)
                }
            }
        },
        modelEditToggle() {
            if (this.isModelEdit) {
                this.isModelEdit = false
            } else {
                this.modelValue = this.model.model
                this.isModelEdit = true;
            }
        },
        modelEditSave() {
            if (!this.modelValue) {
                this.$message.error('请输入唯一字段值')
                return;
            }
            if (typeof this.modelValue === 'string') {
                const value = this.modelValue.trim()
                if (!/^[A-Za-z]\w*$/.test(value)) {
                    this.$message.error('只能包含字母、数字、下划线，且以字母开头')
                    return;
                }
                if (this.widgets.indexOf(value) > -1 && this.widgets.indexOf(value) !== this.widgets.indexOf(this.model.model)) {
                    this.$message.error('改字段值已存在')
                    return;
                }
                this.$set(this.model, 'model', value)
            } else {
                this.$message.error('修改失败')
            }
            this.isModelEdit = false
        }
    }
}
</script>

<style lang="scss" scoped>
.property-edit{
    box-sizing: border-box;
    padding: 10px;
    .property-edit-tab-content{
        height: calc( 100vh - 103px );
    }
    .property-edit-form-common{
        display: flex;
        justify-content: space-between;
        align-items: center;
        color: #409EFF;
        background: #fafafa;
        border-bottom: 1px solid #409EFF;
        padding: 0 10px;
    }
    .property-edit-form{
        box-sizing: border-box;
        padding-right: 10px;
        padding-bottom: 40px;
    }
}
>>>.tree-item{
    width: 90%;
    position: relative;
    .tree-item-label{
        display: inline-block;
        width: 50%;
        overflow: hidden;
    }
    .tree-item-options{
        position: absolute;
        top: 0;
        right: 0;
    }
}
.rules{
    list-style: none;
    padding: 0;
    .rules-type{
        padding-left: 20px;
        margin-bottom: 10px;
    }
    .rules-message{
        padding-left: 20px;
    }
}
.model-edit{
    display: flex;
    align-items: center;
    .model-edit-text{
        max-width: 80%;
        overflow: hidden;
        white-space:nowrap;
        text-overflow:ellipsis;
    }
}
</style>
